package com.example.demo.util.excel;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Description:
 *
 * @Author zmf
 * @Date 2018/11/25  12:10
 */
public class ExcelCreateUtil {

    /**
     * 创建工作簿并初始化第一个sheet数据
     * @param list 数据集合
     * @param keys 数据集合中的Map的key集合
     * @param columnNames 列名集合(表头数据)
     * @param sheetName 第一个sheet页名称
     * @return
     */
    public static Workbook createWorkBook(List<Map<String, Object>> list,
                                          List<String> keys,
                                          List<String> columnNames, String sheetName) {
        // 创建excel工作簿
        XSSFWorkbook wb = new XSSFWorkbook();
        // 创建第一个sheet（页），并命名
        XSSFSheet sheet = wb.createSheet(sheetName);
        initSheet(wb,sheet,columnNames,list, keys);
        return wb;
    }

     /**
     * 建立一个sheet并填充数据
     * @param wb 工作簿
     * @param list 数据集合
     * @param keys 数据集合中的Map的key集合
     * @param columnNames 列名集合(表头数据)
     * @param sheet 初始化建立的sheet
     */
    private static void initSheet(Workbook wb, Sheet sheet, List<String> columnNames,
                                  List<Map<String, Object>> list, List<String> keys) {
        // 手动设置列宽。第一个参数表示要为第几列设；，第二个参数表示列的宽度，n为列高的像素数。
        for(int i=0;i<keys.size();i++){
            sheet.setColumnWidth((short) i, (short) (35.7 * 150));
        }
        // 创建第一行
        Row row = sheet.createRow(0);

        // 创建两种单元格格式
        CellStyle cs1 = wb.createCellStyle();
        CellStyle cs2 = wb.createCellStyle();

        // 创建两种字体
        Font f1 = wb.createFont();
        Font f2 = wb.createFont();

        // 创建第一种字体样式（用于列名）
        f1.setFontHeightInPoints((short) 11);//设置字体大小
        f1.setColor(IndexedColors.BLACK.getIndex());
        f1.setBoldweight(Font.BOLDWEIGHT_BOLD);//粗体显示

        // 创建第二种字体样式（用于值）
        f2.setFontHeightInPoints((short) 11);
        f2.setColor(IndexedColors.BLACK.getIndex());

        // 设置第一种单元格的样式（用于列名）
        cs1.setFont(f1);
//        cs1.setBorderLeft(CellStyle.BORDER_THIN);//左边框
//        cs1.setBorderRight(CellStyle.BORDER_THIN);//右边框
//        cs1.setBorderTop(CellStyle.BORDER_THIN);//上边框
//        cs1.setBorderBottom(CellStyle.BORDER_THIN);//下边框
        cs1.setAlignment(CellStyle.ALIGN_CENTER);//水平居中

        // 设置第二种单元格的样式（用于值）
        cs2.setFont(f2);
//        cs2.setBorderLeft(CellStyle.BORDER_THIN);
//        cs2.setBorderRight(CellStyle.BORDER_THIN);
//        cs2.setBorderTop(CellStyle.BORDER_THIN);
//        cs2.setBorderBottom(CellStyle.BORDER_THIN);
        cs2.setAlignment(CellStyle.ALIGN_CENTER);
        cs2.setWrapText(true);//设置自动换行

        // 设置列名
        for (int i = 0; i < columnNames.size(); i++) {
            Cell cell = row.createCell(i);
            cell.setCellValue(columnNames.get(i));
            cell.setCellStyle(cs1);
        }
        // 设置每行每列的值
        if (list != null && list.size() > 0) {
            for (short i = 0; i < list.size(); i++) {
                // Row 行,Cell 方格 , Row 和 Cell 都是从0开始计数的
                // 创建一行，在页sheet上
                Row row1 = sheet.createRow((short) i + 1);
                // 在row行上创建一个方格
                for (short j = 0; j < keys.size(); j++) {
                    Cell cell = row1.createCell(j);
                    cell.setCellValue(list.get(i).get(keys.get(j)) == null ? " "
                            : list.get(i).get(keys.get(j)).toString());
                    cell.setCellStyle(cs2);
                }
            }
        }
    }

    /**
     * 添加一个sheet
     * @param wb 工作簿
     * @param list 数据集合
     * @param keys 数据集合中的Map的key集合
     * @param columnNames 列名集合(表头数据)
     * @param sheetName sheet页名称
     */
    public static void addSheet(Workbook wb, List<Map<String, Object>> list,
                                List<String> keys, List<String> columnNames,
                                String sheetName) {
        Sheet sheet = wb.createSheet(sheetName);
        initSheet(wb,sheet,columnNames,list, keys);
    }

    /**
     * 对象列表转Map列表
     * @param objList 对象列表
     * @param keys  对象的属性集合
     * @return
     */
    public static List<Map<String, Object>> parseListMap(List<?> objList, List<String> keys) {
        List<Map<String, Object>> list = new ArrayList<>();
        for (Object obj : objList) {
            Map<String, Object> mapValue = new HashMap<>();
            for (String key : keys) {
                mapValue.put(key, getFieldValueByFieldName(key, obj));
            }
            list.add(mapValue);
        }
        return list;
    }

    /**
     * 利用反射  根据属性名获取属性值
     */
    private static String getFieldValueByFieldName(String fieldName, Object obj) {
       /* try {
            String getter = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter);
            return method.invoke(o);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }*/
        if (obj == null){
            return null;
        }
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            if (fieldName.equals(field.getName())) {
                String className = field.getType().getName();
                try {
                    if (field.get(obj) == null) {
                        return "";
                    }
                    //如果是日期类型 则转化
                    if (className.equalsIgnoreCase("Date") || className.equalsIgnoreCase("java.util.Date")) {
                        Date time = (Date) field.get(obj);
                        return dateToString(time, "yyyy-MM-dd HH:mm:ss");
                    }
                    return field.get(obj) + "";
                } catch (IllegalArgumentException | IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    public static String dateToString(Date date, String dateFormat) {
        SimpleDateFormat dateFormatter = new SimpleDateFormat();
        if (date != null && dateFormat != null && dateFormat.trim().length() != 0) {
            dateFormatter.applyPattern(dateFormat);
            return dateFormatter.format(date);
        } else {
            throw new IllegalArgumentException("时间参数或时间格式参数不能为空！");
        }
    }

}
